package com.petrooil.web.controller;

import com.petrooil.core.dao.OrbeonDao;
import com.petrooil.core.model.*;
import com.petrooil.core.model.controller.ModelUser;
import com.petrooil.core.model.controller.ModelWorkflowRule;
import com.petrooil.core.service.IUserService;
import com.petrooil.core.service.IWorkflowRuleService;
import com.petrooil.utils.JsonPagedDataAction;
import com.petrooil.utils.SysListUtils;
import com.petrooil.utils.SysLookup;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpSession;
import java.util.*;

@Controller
public class AdminWorkflowController {

    @Autowired
    private IUserService userService;

    @Autowired
    private IWorkflowRuleService workflowRuleService;

    @Autowired
    private OrbeonDao orbeonDao;

    private String msg;

    private String error;

    @RequestMapping(value = {"/admin/userList" }, method = RequestMethod.GET)
    public ModelAndView showUsersList() {
        ModelAndView model = new ModelAndView();
        model.setViewName("admin/users");
        return model;
    }

    @Transactional(readOnly = true)
    @RequestMapping(value = "/admin/getUserList", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE})
    public @ResponseBody JsonPagedDataAction<ModelUser> getUsersList(HttpSession session) {
        JsonPagedDataAction<ModelUser> data = new JsonPagedDataAction<ModelUser>() {};
        List<ModelUser> list = new ArrayList<>();

        for (User user : userService.findAll()) {
            ModelUser modelUser = new ModelUser();
            modelUser.setLogin(user.getUsername());
            List<String> listTmp = new ArrayList<>();
            for (UserRole userRole : user.getUserRole()) {
                listTmp.add(SysLookup.ROLE.valueOf(userRole.getRole()).getDescription());
            }
            modelUser.setRoles(listTmp);
            modelUser.setDepartments(Arrays.asList(SysLookup.DEPARTMENT.valueOf(user.getUserDepartment().iterator().next().getDepartment()).getDescription()));
            list.add(modelUser);
        }

        data.setData(list);
        return data;
    }

    @RequestMapping(value = {"/admin/workflowRuleList" }, method = RequestMethod.GET)
    public ModelAndView showWorkflowRuleList() {
        ModelAndView model = new ModelAndView();
        model.addObject("msg", msg);
        model.addObject("error", error);
        error = "";
        msg = "";
        model.setViewName("admin/workflowRules");
        return model;
    }

    @RequestMapping(value = "admin/getWorkflowRuleList", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE})
    public @ResponseBody JsonPagedDataAction<WorkflowRule> getWorkflowRuleList(HttpSession session) {
        JsonPagedDataAction<WorkflowRule> data = new JsonPagedDataAction<WorkflowRule>() {};
        List<WorkflowRule> list = new ArrayList<>();
        list = workflowRuleService.findAll();
        data.setData(list);
        return data;
    }

    @RequestMapping(value = {"/admin/addWfRule" }, method = RequestMethod.GET)
    public ModelAndView addWorkflowRuleList() {
        ModelAndView model = new ModelAndView();
        ModelWorkflowRule rule = new ModelWorkflowRule();
        rule.setActions(SysListUtils.stringToList("PDF,TRASH,VIEW,EDIT,ARCHIVE"));
        model.addObject("rule", rule);
        model.setViewName("admin/editWorkflowRule");
        return model;
    }

    @RequestMapping(value = {"/admin/editWfRule" }, method = RequestMethod.GET)
    public ModelAndView editWorkflowRuleList(@RequestParam(value="rule", required=true) Integer id) {
        ModelAndView model = new ModelAndView();
        ModelWorkflowRule rule = new ModelWorkflowRule();
        WorkflowRule workflowRule = workflowRuleService.get(id);

        if (workflowRule == null) {
            error = "Podana reguła nie istnieje.";
            model.setViewName("redirect:/admin/workflowRuleList");
            return model;
        }

        rule.setRuleId(workflowRule.getRuleId());
        rule.setDepartment(workflowRule.getDepartment() + ":" + workflowRule.getForm());
        rule.setForm(workflowRule.getForm());
        rule.setDestinationDepartment(workflowRule.getDestinationDepartment());
        rule.setActions(SysListUtils.stringToList(workflowRule.getActions()));
        rule.setFlows(SysListUtils.stringToList(workflowRule.getFlows()));

        model.addObject("rule", rule);
        model.setViewName("admin/editWorkflowRule");
        return model;
    }

    @RequestMapping(value = {"/admin/resetWfRule" }, method = RequestMethod.GET)
    public ModelAndView resetWorkflowRuleList(@RequestParam(value="rule", required=true) Integer id) {
        ModelAndView model = new ModelAndView();
        WorkflowRule workflowRule = workflowRuleService.get(id);

        if (workflowRule == null) {
            error = "Podana reguła nie istnieje.";
            model.setViewName("redirect:/admin/workflowRuleList");
            return model;
        }

        workflowRule.setFlows("");
        workflowRule.setActions("");
        workflowRuleService.update(workflowRule);

        msg = "Poprawnie zresetowano regułę.";
        model.setViewName("redirect:/admin/workflowRuleList");
        return model;
    }

    @RequestMapping(value = {"/admin/deleteWfRule" }, method = RequestMethod.GET)
    public ModelAndView deleteWorkflowRuleList(@RequestParam(value="rule", required=true) Integer id) {
        ModelAndView model = new ModelAndView();
        WorkflowRule workflowRule = workflowRuleService.get(id);

        if (workflowRule == null) {
            error = "Podana reguła nie istnieje.";
            model.setViewName("redirect:/admin/workflowRuleList");
            return model;
        }

        workflowRuleService.delete(workflowRule);

        msg = "Poprawnie usunięto regułę.";
        model.setViewName("redirect:/admin/workflowRuleList");
        return model;
    }

    @ModelAttribute("departmentsFlowMap")
    public Map<String, String> getDepartmentsFlowMap() {
        Map<String, String> map = new HashMap<>();
        for (SysLookup.DEPARTMENT d : SysLookup.DEPARTMENT.values()) {
            map.put(d.toString(), d.getDescription());
        }
        map.remove(SysLookup.DEPARTMENT.ARCHIVE.toString());
        map.remove(SysLookup.DEPARTMENT.TRASH.toString());
        return map;
    }

    @ModelAttribute("departmentsMap")
    public Map<String, String> getDepartmentsMap() {
        Map<String, String> map = new HashMap<>();
        for (SysLookup.DEPARTMENT d : SysLookup.DEPARTMENT.values()) {
            map.put(d.toString(), d.getDescription());
        }
        return map;
    }

    @ModelAttribute("actionsMap")
    public Map<String, String> getActionsMap(){
        Map<String, String> map = new HashMap<>();
        for (SysLookup.ACTION a : SysLookup.ACTION.values()) {
            map.put(a.toString(),a.getDescription());
        }
        return map;
    }

    @ModelAttribute("formsMap")
    public Map<String, String> getFormsMap() {
        List<Map<String, String>> listForms = orbeonDao.getAllForms();
        Map<String, String> formMap = new HashMap<>();
        for (Map<String, String> map : listForms) {
            formMap.put(map.get(SysLookup.OrbeonColums.DEFINITION_APP) + ":" + map.get(SysLookup.OrbeonColums.DEFINITION_FORM),
                    SysLookup.DEPARTMENT.valueOf(map.get(SysLookup.OrbeonColums.DEFINITION_APP)).getDescription() + ":" + map.get(SysLookup.OrbeonColums.DEFINITION_FORM));
        }
        return formMap;
    }

    @RequestMapping(value = {"/admin/saveWorkflowRule" }, method = RequestMethod.POST)
    public ModelAndView saveWorkflowRuleList(@ModelAttribute("rule") ModelWorkflowRule rule) {
        ModelAndView model = new ModelAndView();

        //walidacja

        WorkflowRule workflowRule = new WorkflowRule();
        workflowRule.setRuleId(rule.getRuleId() != null ? rule.getRuleId() : null);
        workflowRule.setForm(rule.getDepartment().split(":")[1]);
        workflowRule.setDepartment(rule.getDepartment().split(":")[0]);
        workflowRule.setDestinationDepartment(rule.getDestinationDepartment());
        workflowRule.setActions(SysListUtils.listToString(rule.getActions()));
        workflowRule.setFlows(SysListUtils.listToString(rule.getFlows()));
        try {
            if (workflowRule.getRuleId() != null) {
                workflowRuleService.update(workflowRule);
                msg  ="Poprawnie zaktualizowano regułę workflow";
            } else {
                workflowRuleService.create(workflowRule);
                msg = "Poprawnie dodano regułę workflow";
            }
        } catch (ConstraintViolationException e) {
            model.addObject("error", "Taka reguła już istnieje.");
            model.addObject("rule", rule);
            model.setViewName("admin/editWorkflowRule");
            return  model;
        }

        model.setViewName("redirect:/admin/workflowRuleList");
        return model;
    }
}
